#include "stdafx.h"
#include "..\Lab2_GOST\GOST_Cipher.h"
#include "..\Lab2_GOST\GOST_Cipher.cpp"

using namespace std;

void print_hash(init_vector x)
{
	printf("Hash is\n");
	for(ubyte i=0;i<IV_X;++i)
		printf("%u %u \n",x.val[i].r,x.val[i].l);
	printf("\n");
}

uint hamdist(uint x, uint y)
{
  uint dist = 0, val = x ^ y;
  // Count the number of set bits
  while(val)
  {
    ++dist; 
    val &= val - 1;
  }
  return dist;
} 
#include <time.h>
int main(int argc, char* argv[])
{
	//==========create cipher=========//
	uint key[]={0,1,2,3,4,5,6,7};
    block A[]= {block(1,2),
	            block(10,20),
			    block(100,200),
			    block(1000,2000)};
	init_vector iv(A);
	GOST_Cipher c(key,iv);
	//===========get text============//
	text plain;
	plain.push_back(block(1,2));
	plain.push_back(block(3,4));
	plain.push_back(block(5,6));
	plain.push_back(block(7,8));
	plain.push_back(block(9,10));
	
	//===========print hash=============//
	
	//cout<<"Source text\n";
	init_vector hash=c.Get_Hash(plain);

	printf("block_number  bit_number  hem_dist \n");
	const uint TIMES=20;
	srand(unsigned(time(0)));
	for(ubyte i=1;i<TIMES;++i)
	{
		uint block_number=rand()%plain.size();
		uint bit=rand()%(sizeof(block)*BITS_IN_BYTE);
		uint bit_changed=block_number*(sizeof(block)*BITS_IN_BYTE)+bit;

		//change (bit/2)-th bit in (block_number)-th block
		if(bit%2)
			plain[block_number].r^=(1<<(bit/2));
		else
			plain[block_number].l^=(1<<(bit/2));
		init_vector changed_hash=c.Get_Hash(plain);

		//hamming distance
		uint distance=0;
		for(uint j=0;j<IV_X;++j)
			distance+=(hamdist(hash.val[j].l,changed_hash.val[j].l)
			          +hamdist(hash.val[j].r,changed_hash.val[j].r));

		//print results
		printf("%u\t", block_number);
		printf("\t%u\t", bit);
		printf("\t%u\t\n", distance);
		hash=changed_hash;
		//print_hash(c.Get_Hash(plain));
	}
	//init_vector hash=FileCipher::Get_Hash("Tux.bmp",&c);
	//FileCipher::Encipher("Tux.bmp","encoded",&c,CBC);
	//FileCipher::Decipher("encoded","decode.bmp",&c,CBC);
	return 0;
}
